package com.lv.phuotbacnam.bl.network.util.location;

import android.content.Context;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationManager;
import android.os.AsyncTask;

import com.lv.phuotbacnam.bl.callback.ThreadSafeResultCallback;
import com.lv.phuotbacnam.bl.log.Logger;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

/**
 * Created by VanQuan on 26/08/2014. To get current location from GPS if it's
 * available else get from network provider
 */
public class LocationHelper {
	private Context mContext;
	private AppLocationService appLocationService;

	public LocationHelper(Context context) {
		this.mContext = context;
		appLocationService = new AppLocationService(context);
	}

	public boolean checkLocationTurned() {
		return appLocationService.checkLocationTurned();

	}

	public Location getLocation() {
		Location gpsLocation = appLocationService
				.getLocation(LocationManager.GPS_PROVIDER);

		if (gpsLocation != null)
			return gpsLocation;
		else
			return appLocationService
					.getLocation(LocationManager.NETWORK_PROVIDER);
	}

	/**
	 * @return Current address
	 */
	public void getCurrentAddress(Location lc,
			ThreadSafeResultCallback<Object, String> callback) {
		if (lc != null)
			new getCurAddAsyTask(lc, callback).execute();
		else
			callback.doOnSuccess("", "");

		// getAddressString(getFromLocation(lc.getLatitude(),lc.getLongitude()));

	}

	/**
	 * @return Current address
	 */
	public void getCurrentAddress(
			ThreadSafeResultCallback<Object, String> callback) {
		Location lc = getLocation();
		new getCurAddAsyTask(lc, callback).execute();
	}

	private class getCurAddAsyTask extends AsyncTask<String, Void, String> {
		private Location mLc;
		private ThreadSafeResultCallback<Object, String> mCallBack;

		public getCurAddAsyTask(Location lc,
				ThreadSafeResultCallback<Object, String> callback) {
			this.mCallBack = callback;
			this.mLc = lc;

			Logger.logMessage("Address: " + lc.getLatitude() + " - "
					+ lc.getLongitude());
		}

		@Override
		protected String doInBackground(String... strings) {
			StringBuilder strReturnedAddress = new StringBuilder("");
			Geocoder geocoder = new Geocoder(mContext, Locale.ENGLISH);
			try {
				List<Address> addresses = geocoder.getFromLocation(
						this.mLc.getLatitude(), this.mLc.getLongitude(), 1);
				strReturnedAddress = getAddressString(addresses);
			} catch (Exception e) {
				Logger.logMessage("Error get Address: " + e.getMessage());
				return "";
			}
			return strReturnedAddress.toString();
		}

		@Override
		protected void onPostExecute(String s) {
			super.onPostExecute(s);
			Logger.logMessage("s address: " + s);
			this.mCallBack.doOnSuccess("", s);
		}
	}

	private StringBuilder getAddressString(List<Address> addresses) {
		StringBuilder strReturnedAddress = new StringBuilder("");
		if (addresses != null) {
			Address returnedAddress = addresses.get(0);
			Logger.logMessage("AdminArea: " + returnedAddress.getAdminArea());
			for (int i = 0; i < returnedAddress.getMaxAddressLineIndex(); i++) {
				if (i < returnedAddress.getMaxAddressLineIndex() - 1)
					strReturnedAddress
							.append(returnedAddress.getAddressLine(i)).append(
									", ");
				else
					strReturnedAddress
							.append(returnedAddress.getAddressLine(i));
			}
		} else {
			Logger.logMessage("address = null");
			return strReturnedAddress;
		}
		return strReturnedAddress;
	}

	public static List<Address> getFromLocation(double lat, double lng) {

		String address = String
				.format(Locale.ENGLISH,
						"http://maps.googleapis.com/maps/api/geocode/json?latlng=%1$f,%2$f&sensor=true&language="
								+ Locale.getDefault().getCountry(), lat, lng);
		HttpGet httpGet = new HttpGet(address);
		HttpClient client = new DefaultHttpClient();
		HttpResponse response;
		StringBuilder stringBuilder = new StringBuilder();

		List<Address> retList = null;

		try {
			response = client.execute(httpGet);
			HttpEntity entity = response.getEntity();
			InputStream stream = entity.getContent();
			int b;
			while ((b = stream.read()) != -1) {
				stringBuilder.append((char) b);
			}

			JSONObject jsonObject = new JSONObject();
			jsonObject = new JSONObject(stringBuilder.toString());

			retList = new ArrayList<Address>();

			if ("OK".equalsIgnoreCase(jsonObject.getString("status"))) {
				JSONArray results = jsonObject.getJSONArray("results");
				for (int i = 0; i < results.length(); i++) {
					JSONObject result = results.getJSONObject(i);
					String indiStr = result.getString("formatted_address");
					Address addr = new Address(Locale.ITALY);
					addr.setAddressLine(0, indiStr);
					retList.add(addr);
				}
			}

		} catch (ClientProtocolException e) {
			Logger.logMessage("Error calling Google geocode webservice." + e);
		} catch (IOException e) {
			Logger.logMessage("Error calling Google geocode webservice." + e);
		} catch (JSONException e) {
			Logger.logMessage("Error parsing Google geocode webservice response."
					+ e);
		}

		return retList;
	}
}
